#ifndef __tenacitas_symbols_traverser_core__word__h__
#define __tenacitas_symbols_traverser_core__word__h__



/** @file */


/** @todo */

// ==> C++ Headers
#include <string>
#include <iostream>

// ==> 3rds Headers

// ==> Our Headers
#include <tenacitas.return_code.core/rc.h>


// ==> Namespaces
using namespace std;

// ==> Macro Constants

// ==> Macro Commands


/** ==> namespace of the organization */
namespace tenacitas {
    /** ==> namespace for the project */
    namespace symbols_traverser {
        /** ==> bussiness, core, displaying, interacting, transmitting,
            storing */ 
        namespace core {

            // ==> Typedefs 

            // ==> Pre-Declarations

            // ==> Attributes 

            // ==> Functions

            // ==> Classes

            /**
               @tparam supplier must define @p text and @p letter

               @tparam supplier::text is the type of string to be
               used: @p std::string, or @p std::wstring, or @p std::u16string, or
               @p std::u32string. 

               @nosubgrouping
            */
            template <typename supplier>
            class word {

            public:

                // ==> word - Public Internal Types

                /** */
                typedef typename supplier::text text;

                /** */
                enum category : constant_id { 
                        very_easy = 10,
                        easy = 20,
                        medium = 50,
                        difficult = 80,
                        very_difficult = 100,
                        impossible = 200
                        };
                
                // ==> word - Friends

                /** Class allowed to access private members of @p word, in
                    order to perform tests */
                friend class word_tester;

                friend std::ostream & operator << (std::ostream & p_out,
                                                   const word & p_word) {
                    p_out << p_word.m_value
                          << ", " << p_word.m_hint
                          << ", " << p_word.m_category;
                    return p_out;
                }
                

                // ==> word - Public Constructors

                /** */
                inline word(const text & p_value,
                            const text & p_hint,
                            category  p_category) ;

                /** */
                inline word(const word & p_word) ;

                /** */
                inline word(word && p_word) noexcept;

                /** Destructor */
                inline ~word();

                // ==> word - Public Accessors

                /** */
                const category & get_category() const noexcept;

                /** */
                const text & get_text() const noexcept;

                /** */
                const text & get_hint() const noexcept;

                // ==> word - Public Operators

                /** */
                inline word & operator=(const word & p_word) noexcept;
                
                /** */
                inline word & operator=(word && p_word) noexcept;

                /** */
                inline bool operator ==(const word & p_word) const noexcept;

                /** */
                inline bool operator !=(const word & p_word) const noexcept;

                /** */
                inline bool operator >=(const word & p_word) const noexcept;

                /** */
                inline bool operator >(const word & p_word) const noexcept;

                /** */
                inline bool operator <=(const word & p_word) const noexcept;

                /** */
                inline bool operator <(const word & p_word) const noexcept;

                /** not allowed */
                void* operator new (std::size_t size)
                    throw (std::bad_alloc) = delete;

                /** not allowed */
                void operator delete (void *p_logger) = delete;

                /** not allowed */
                void *operator new[] (size_t) = delete;

                /** not allowed */
                void operator delete[] (void *) = delete;

                // ==> word - Public Attributes

                /** */
                static const class_id id = 1427745122ULL;

            private:

                // ==> word - Private Attributes

                /** */
                text m_value;

                /** */
                text m_hint;

                /** */
                category m_category;
                
            };
        }
    }
}
// =============================================================================
// I M P L E M E N T A T I O N
// =============================================================================

using namespace tenacitas::symbols_traverser::core;

// -----------------------------------------------------------------------------
template<typename supplier>
word<supplier>::
word(const text & p_value,
     const text & p_hint,
     category p_category) 
    : m_value(p_value),
    m_hint(p_hint),
    m_category(p_category) {}

// -----------------------------------------------------------------------------
template<typename supplier>
word<supplier>::
word(const word & p_word) 
    : m_value(p_word.m_value),
    m_hint(p_word.m_hint),
    m_category(p_word.m_category) {}

// -----------------------------------------------------------------------------
template<typename supplier>
word<supplier>::                
word(word && p_word) noexcept {
    m_value = std::move(p_word.m_value);
    m_hint = std::move(p_word.m_hint);
    m_category = std::move(p_word.m_category);
}

// -----------------------------------------------------------------------------
template<typename supplier>
word<supplier>::
~word() {}

// -----------------------------------------------------------------------------
template<typename supplier>
const typename word<supplier>::category &
word<supplier>::
get_category() const noexcept {return m_category;}

// -----------------------------------------------------------------------------
template<typename supplier>
const typename word<supplier>::text &
word<supplier>::
get_text() const noexcept {return m_value;}

// -----------------------------------------------------------------------------
template<typename supplier>
const typename word<supplier>::text &
word<supplier>::
get_hint() const noexcept {return m_hint;}

// -----------------------------------------------------------------------------
template<typename supplier>
word<supplier> &
word<supplier>::
operator=(const word & p_word) noexcept {
    if (this != & p_word) {       
        m_value = p_word.m_value;
        m_hint = p_word.m_hint;
        m_category = p_word.m_category;
    }
    return *this;
}

// -----------------------------------------------------------------------------
template<typename supplier>
word<supplier> &
word<supplier>::
operator=(word && p_word) noexcept {
    if (this != & p_word) {
        m_value = std::move(p_word.m_value);
        m_hint = std::move(p_word.m_hint);
        m_category = std::move(p_word.m_category);
    }
    return *this;
}

// -----------------------------------------------------------------------------
template<typename supplier>
bool
word<supplier>::
operator ==(const word & p_word) const noexcept {
    return m_value == p_word.m_value;
}

// -----------------------------------------------------------------------------
template<typename supplier>
bool
word<supplier>::
operator !=(const word & p_word) const noexcept  {
    return m_value != p_word.m_value;
}

// -----------------------------------------------------------------------------
template<typename supplier>
bool
word<supplier>::
operator >=(const word & p_word) const noexcept  {
    return m_value >= p_word.m_value;
}

// -----------------------------------------------------------------------------
template<typename supplier>
bool
word<supplier>::
operator >(const word & p_word) const noexcept  {
    return m_value > p_word.m_value;
}

// -----------------------------------------------------------------------------
template<typename supplier>
bool
word<supplier>::
operator <=(const word & p_word) const noexcept {
    return m_value <= p_word.m_value;
}

// -----------------------------------------------------------------------------
template<typename supplier>
bool
word<supplier>::
operator <(const word & p_word) const noexcept {
    return m_value < p_word.m_value;
}



#endif
